#include "main.h"
#include "stm32g4xx_hal.h"

// 防抖相关定义
#define DEBOUNCE_TIME_MS    20      // 防抖时间20ms
#define KEY_PRESSED         0       // 按键按下时的电平（低电平有效）
#define KEY_RELEASED        1       // 按键释放时的电平

// 按键状态结构体
typedef struct 
{
    uint16_t pin;                   // GPIO引脚
    GPIO_TypeDef* port;             // GPIO端口
    uint32_t last_interrupt_time;   // 上次中断时间
    uint8_t last_state;             // 上次稳定状态
    uint8_t debounce_flag;          // 防抖标志
} key_debounce_t;

// 按键实例
static key_debounce_t keys[] = 
{
    {key0_Pin, key0_GPIO_Port, 0, KEY_RELEASED, 0},
    {key1_Pin, key1_GPIO_Port, 0, KEY_RELEASED, 0},
    {key2_Pin, key2_GPIO_Port, 0, KEY_RELEASED, 0}
};

#define KEY_COUNT (sizeof(keys) / sizeof(keys[0]))

/**
 * @brief 获取系统时间戳（毫秒）
 */
static uint32_t get_tick_ms(void)
{
    return HAL_GetTick();
}

/**
 * @brief 读取按键当前状态
 */
static uint8_t read_key_state(key_debounce_t* key)
{
    return HAL_GPIO_ReadPin(key->port, key->pin);
}

/**
 * @brief 查找按键索引
 */
static int find_key_index(uint16_t gpio_pin)
{
    for (int i = 0; i < KEY_COUNT; i++)
    {
        if (keys[i].pin == gpio_pin)
        {
            return i;
        }
    }
    return -1;
}

/**
 * @brief 按键事件处理函数（用户实现）
 */
void key_pressed_handler(uint16_t gpio_pin)
{
    switch (gpio_pin)
    {
        case key0_Pin:
            // KEY0按下处理
            printf("KEY0 pressed\n");
            break;
            
        case key1_Pin:
            // KEY1按下处理
            printf("KEY1 pressed\n");
            break;
            
        case key2_Pin:
            // KEY2按下处理
            printf("KEY2 pressed\n");
            break;
            
        default:
            break;
    }
}

/**
 * @brief 按键释放事件处理函数（用户实现）
 */
void key_released_handler(uint16_t gpio_pin)
{
    switch (gpio_pin)
    {
        case key0_Pin:
            // KEY0释放处理
            printf("KEY0 released\n");
            break;
            
        case key1_Pin:
            // KEY1释放处理
            printf("KEY1 released\n");
            break;
            
        case key2_Pin:
            // KEY2释放处理
            printf("KEY2 released\n");
            break;
            
        default:
            break;
    }
}

/**
 * @brief GPIO外部中断回调函数（重写HAL库的弱函数）
 */
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    int key_index = find_key_index(GPIO_Pin);
    if (key_index < 0)
    {
        return;
    }
    
    key_debounce_t* key = &keys[key_index];
    uint32_t current_time = get_tick_ms();
    
    // 检查是否在防抖时间内
    if ((current_time - key->last_interrupt_time) < DEBOUNCE_TIME_MS)
    {
        return; // 忽略抖动
    }
    
    // 更新中断时间
    key->last_interrupt_time = current_time;
    
    // 读取当前按键状态
    uint8_t current_state = read_key_state(key);
    
    // 状态发生变化
    if (current_state != key->last_state)
    {
        key->last_state = current_state;
        
        if (current_state == KEY_PRESSED)
        {
            // 按键按下
            key_pressed_handler(GPIO_Pin);
        }
        else
        {
            // 按键释放
            key_released_handler(GPIO_Pin);
        }
    }
}

/**
 * @brief 按键防抖初始化
 */
void key_debounce_init(void)
{
    // 初始化按键状态
    for (int i = 0; i < KEY_COUNT; i++)
    {
        keys[i].last_state = read_key_state(&keys[i]);
        keys[i].last_interrupt_time = 0;
        keys[i].debounce_flag = 0;
    }
} 